package com.central.apps.handler.project;

import com.central.app.common.base.BaseHandler;
import com.central.app.service.FlowCommonService;
import com.central.app.service.HandlerService;
import com.central.app.service.TreeService;
import com.central.app.service.VersionService;
import com.central.apps.common.util.MapCustomUtils;
import com.central.apps.service.*;
import com.central.bizcommon.model.flow.FlowNode;
import com.central.bizcommon.model.flow.FlowOpinion;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理项目年度业务逻辑
 *
 * @author lidachao
 * @date 2023/4/10
 */
@Component
@Slf4j
public class ProjectPlanHandler extends BaseHandler {

    @Autowired
    private HandlerService handlerService;
    @Autowired
    private BudgetService budgetService;
    @Autowired
    private VersionService versionService;
    @Autowired
    private TreeService treeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FlowCommonService flowCommonService;
    @Autowired
    private TaskStatisticsService taskStatisticsService;

    @Override
    public Object operate(String app, String type, Map<String, Object> params) throws Exception {
        if ("getHistoryBudget".equals(type)) {
            List<Map<String, Object>> list = treeService.findTreeV1(app, params, false);

            if (CollectionUtils.isNotEmpty(list)) {
                Integer proId = MapUtils.getInteger(params, "proid");
                for (Map<String, Object> map : list) {
                    Integer pbiId = MapUtils.getInteger(map, "pbiid");

                    Map<String, Object> blMap = handlerService.findOneBySql("select budgetamt, usefulamt from gq_pblbestimate where proid = " + proId + " and pbiid = " + pbiId);

                    if (blMap != null && !blMap.isEmpty()) {
                        map.put("blbudgetamt", blMap.get("budgetamt"));
                        map.put("blusefulamt", blMap.get("usefulamt"));
                    }
                }

                JSONObject json = new JSONObject();
                json.put("code", "0");
                json.put("count", list.size());
                json.put("data", list);
                return json;
            }
        }
        if ("getCostFill".equals(type)) {
            Integer id = MapUtils.getInteger(params, "id");
            Integer pbiId = MapUtils.getInteger(params, "pbiid");
            Integer proId = MapUtils.getInteger(params, "proid");
            String year = MapUtils.getString(params, "year");

            List<Map<String, Object>> list = handlerService.findBySql("select id from gq_probudget where proid = " + proId + " and year = '" + year + "' and (pbiparentid = " + pbiId + " or id = " + id + ")");

            StringBuilder sb = new StringBuilder();
            for (Map<String, Object> map : list) {
                sb.append(MapUtils.getInteger(map, "id")).append(",");
            }

            sb.deleteCharAt(sb.length() - 1);

            list = handlerService.findBySql("select id, cfnum, cfdesc, type, costsource, totalcost, dutycenter, createuserdesc, DATE_FORMAT(createtime, '%Y-%m-%d %H:%i:%s') AS createtime from gq_procostfill where  status in ('已批准','已生成','已分配','未分配') and proid = " + proId + " and pbdid in (" + sb + ") ");

            if (CollectionUtils.isNotEmpty(list)) {
                JSONObject json = new JSONObject();
                json.put("code", "0");
                json.put("count", list.size());
                json.put("data", list);
                return json;
            }
        }
        return null;
    }

    @Override
    public String validateSave(String app, String objName, Map<String, Object> data) throws Exception {
        if ("gq_proplan".equals(objName)) {
            // 校验年度计划是否重复
            Integer id = MapUtils.getInteger(data, "id");
            Integer proId = MapUtils.getInteger(data, "proid");
            Integer year = MapUtils.getInteger(data, "year");

            StringBuilder sql = new StringBuilder();
            sql.append("select id from gq_proplan where status != '已作废' and proid = ").append(proId).append(" and year = ").append(year);
            if (id != null) {
                sql.append(" and id != ").append(id);
            }

            List<Map<String, Object>> list = handlerService.findBySql(sql.toString());

            if (CollectionUtils.isNotEmpty(list)) {
                return "课题号已经存在该实施策划, 请重新进行编制!";
            }

            // 校验预算是否超出预算基线金额
            List<Map<String, Object>> childList = MapCustomUtils.combineChildList(data, "TableUKey86100");

            if (CollectionUtils.isNotEmpty(childList)) {
                String result = budgetService.judgeBeyondBudget(proId, childList);

                if (StringUtils.isNotEmpty(result)) {
                    return result;
                }
            }
        }

        return null;
    }

    @Override
    public void afterSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        if ("gq_proplan".equals(objName)) {
            Integer year = MapUtils.getInteger(data, "year");
            // 更新年度开始和结束日期
            if (MapUtils.getObject(data, "startdate") == null) {
                LocalDate yearStartDate = LocalDate.of(year, 1, 1);
                int weekInt = yearStartDate.getDayOfWeek().getValue();
                if (weekInt > 5) {
                    yearStartDate = LocalDate.of(year, 1, 1+(7-weekInt)+1);
                }

                LocalDate yearEndDate = LocalDate.of(year, 12, 31);
                weekInt = yearEndDate.getDayOfWeek().getValue();
                if (weekInt > 5) {
                    yearEndDate = LocalDate.of(year, 1, 31-(weekInt-5));
                }

                Map<String, Object> updMap = new HashMap<>();
                updMap.put("id", data.get("id"));
                updMap.put("startdate", yearStartDate);
                updMap.put("enddate", yearEndDate);
                handlerService.update(objName, updMap);
            }
        }
    }

    @Override
    public String beforeExcuteFlow(String app, Long id, FlowNode flowNode, FlowOpinion op) throws Exception {
        Map<String, Object> proPlanMap = op.getVariables();
        Integer proId = MapUtils.getInteger(proPlanMap, "proid");
        Integer year = MapUtils.getInteger(proPlanMap, "year");

        // 校验是否编制了项目成员、年度计划以及年度预算
        if ("capture".equals(flowNode.getId())) {
            Map<String, String> map = new HashMap<>(3);
            map.put("gq_proresource", "项目资源");
            map.put("gq_scheduleplantask", "年度计划");
            map.put("gq_probudget", "年度预算");

            StringBuilder prompt = new StringBuilder();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                StringBuilder sql = new StringBuilder();
                sql.append("select id from ").append(entry.getKey()).append(" where 1 = 1 ");

                if (!"年度预算".equals(entry.getValue())) {
                    sql.append(" and proid = ").append(proId);
                } else {
                    sql.append(" and ppid = ").append(id);
                }

                List<Map<String, Object>> list = handlerService.findBySql(sql.toString());
                if (CollectionUtils.isEmpty(list)) {
                    prompt.append(entry.getValue()).append(",");
                }
            }

            if (StringUtils.isNotEmpty(prompt)) {
                prompt.deleteCharAt(prompt.length() - 1);
                prompt.append("等信息未维护, 请编制后再进行提交!");
                return prompt.toString();
            }

            // 判断WBS任务是否存在负责人为空数据
            List<Map<String, Object>> list = handlerService.findBySql("select id from gq_scheduleplantask where parentId != 0 and (manager = 0 or manager is null) and proid = " + proId);

            if (CollectionUtils.isNotEmpty(list)) {
                return "存在任务未分配负责人!";
            }

            // 更新任务不可编辑
            handlerService.updateBySql("update gq_scheduleplantask set isreadonly = 1 where proid = " + proId);
        }

        if("complete".equals(flowNode.getId())) {
            // 更新年度预算状态
            handlerService.updateBySql("update gq_probudget set status = '执行中' where ppid = " + id);

            // 查询年度预算
            List<Map<String, Object>> list = handlerService.findBySql("select pbiid, budgetamt from gq_probudget where ppid = " + id);

            // 更新项目概算已申金额
            budgetService.updateBudgetApplyAmt(proId, list);

            // 存储项目资源新版本
            List<Map<String, Object>> proResourceList = handlerService.findBySql("select * from gq_proresource where proid = " + proId);
            if (CollectionUtils.isNotEmpty(proResourceList)) {
                String conditionStr = " proid = " + proId;
                versionService.saveData("gq_proresource", conditionStr, proResourceList);
            }

            // TODO 计算关键路径

            // 复制计划到我的任务
            taskService.copyToMyTask(proId);

            // 下发任务
            handlerService.updateBySql("update gq_scheduleplantask set isissued = 1 where isissued = 0 and proid = " + proId);

            // 统计项目任务信息
            taskStatisticsService.taskStatistics(proId);
        }

        return null;
    }

    @Override
    public void afterMoveNode(String app, Long id) throws Exception {
        Map<String, Object> map = handlerService.findOneBySql("select status from gq_proplan where id = " + id);
        Integer proId = MapUtils.getInteger(map, "proid");
        boolean isReturnInitNode = flowCommonService.isSubmitNode(app, id);

        if (isReturnInitNode) {
            handlerService.updateBySql("update gq_scheduleplantask set isreadonly = 0 where proid = " + proId);
        }
    }
}
